package com.liuhongwei.test.builder;


import com.liuhongwei.test.bean.Constants;
import com.liuhongwei.test.bean.FieldInfo;
import com.liuhongwei.test.bean.TableInfo;
import com.liuhongwei.test.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;


public class BuildServiceImpl {

    private static final Logger log = LoggerFactory.getLogger(BuildServiceImpl.class);


    public static void execute(TableInfo tableInfo) {
        File folder = new File(Constants.PATH_SERVICE_IMPL);
        if (!folder.exists()) {
            folder.mkdirs();
        }

        OutputStream os = null;
        OutputStreamWriter osw = null;
        BufferedWriter bw = null;
        try {
            String beanName = tableInfo.getBeanName();
            String beanParamName = tableInfo.getBeanParamName();
            String interfaceName = beanName + "Service";
            String className = beanName + "ServiceImpl";
            String mapperName = beanName + "Extend" + Constants.SUFFIX_MAPPER;

            os = new FileOutputStream(folder + "/" + className + ".java");
            osw = new OutputStreamWriter(os, "UTF-8");
            bw = new BufferedWriter(osw);

            bw.write("package " + Constants.PACKAGE_SERVICE_IMPL + ";\n\n");
            //写入Import
            writeImport(bw, beanName, beanParamName, interfaceName, mapperName);
            //写入类注释
            BuildComment.createClassComment(bw, tableInfo.getComment() + "ServiceImpl");
            bw.write("@Service(\"" + StringUtils.lowerCaseFirst(interfaceName) + "\")\n");
            bw.write("public class " + className + " implements " + interfaceName + " {\n\n");

            //写入属性
            writeField(tableInfo, bw, beanName, beanParamName, mapperName);

            bw.write("}");
            bw.flush();
        } catch (Exception e) {
            log.error("创建Service失败", e);
        } finally {
            BuildBase.close(os, osw, bw);
        }
    }


    private static void writeField(TableInfo tableInfo, BufferedWriter bw, String beanName, String beanParamName,
            String mapperName) throws Exception {
        String mapperBeanName = StringUtils.lowerCaseFirst(mapperName);

        bw.write("\t@Resource\n");
//        bw.write("\tprivate " + mapperName + "<" + beanName + ", " + beanParamName + "> " + mapperBeanName + ";\n\n");
        bw.write("\tprivate " + mapperName  + " " + mapperBeanName + ";\n\n");

//        BuildComment.createFieldComment(bw, "根据条件查询列表");
//        bw.write("\tpublic List<" + beanName + "> findListByParam(" + beanParamName + " query) {\n");
//        bw.write("\t\treturn this." + mapperBeanName + ".selectList(query);\n");
//        bw.write("\t}\n\n");
//
//        BuildComment.createFieldComment(bw, "根据条件查询数量");
//        bw.write("\tpublic Integer findCountByParam(" + beanParamName + " query) {\n");
//        bw.write("\t\treturn this." + mapperBeanName + ".selectCount(query);\n");
//        bw.write("\t}\n\n");
//
//        BuildComment.createFieldComment(bw, "分页查询");
//        bw.write("\tpublic PaginationResultVO<" + beanName + "> findListByPage(" + beanParamName + " query) {\n");
//        bw.write("\t\tInteger count = this.findCountByParam(query);\n");
//        bw.write("\t\tSimplePage page = new SimplePage(query.getPageNo(), query.getPageSize(), count);\n");
//        bw.write("\t\tquery.setSimplePage(page);\n");
//        bw.write("\t\tList<" + beanName + "> list = this.findListByParam(query);\n");
//        bw.write("\t\tPaginationResultVO<" + beanName
//                + "> result = new PaginationResultVO(count, page.getPageSize(), page.getPageNo(), page.getCountPage(), list);\n");
//        bw.write("\t\treturn result;\n");
//        bw.write("\t}\n\n");
//
//        BuildComment.createFieldComment(bw, "新增");
//        bw.write("\tpublic Integer add(" + beanName + " bean) {\n");
//        bw.write("\t\treturn this." + mapperBeanName + ".insert(bean);\n");
//        bw.write("\t}\n\n");


        String assemble = StringUtils.upperCaseFirst(tableInfo.getBeanName()) + Constants.SUFFIX_ASSEMBLE;
        String bean = StringUtils.lowerCaseFirst(tableInfo.getBeanName());
        String clazzBean = StringUtils.upperCaseFirst(tableInfo.getBeanName());

        BuildComment.createFieldComment(bw, "页面分页查询");
        bw.write("\t@Override\n");
        bw.write("\tpublic JSONResponse getPage(JSONRequest jsonRequest) throws BusinessException {\n");
        bw.write("\t\tJSONObject jsonObjectData = jsonRequest.getJsonObjectData();\n");
        bw.write(String.format("\t\t%s pageQuery = %s.toPageQuery(jsonObjectData);\n", tableInfo.getBeanParamName(), assemble));
        bw.write(String.format("\t\tInteger totalSize = %s.selectCount(pageQuery);\n", mapperBeanName));
        bw.write("\t\tList<JSONObject> pageList = new ArrayList<>();\n");
        bw.newLine();
        bw.write("\t\tif (totalSize > 0) {\n");
        bw.write(String.format("\t\t\tList<%s> pageRecords = %s.selectList(pageQuery);\n", tableInfo.getBeanName(), mapperBeanName));
        bw.write(String.format("\t\t\tfor (%s pageRecord : pageRecords) {\n", tableInfo.getBeanName()));
        bw.write(String.format("\t\t\t\tpageList.add(%s.toPageJSONObject(pageRecord));\n", assemble));
        bw.write("\t\t\t}\n");
        bw.write("\t\t}\n");
        bw.newLine();
        bw.write("\t\tPage<JSONObject> pageResult = new Page<>(pageQuery.getCurrentPage(), pageQuery.getPageSize(), totalSize, pageList);\n");
        bw.write("\t\treturn JSONResponse.success(pageResult);\n");
        bw.write("\t}\n\n");

        BuildComment.createFieldComment(bw, "页面新增");
        bw.write("\t@Override\n");
        bw.write("\t@Transactional(rollbackFor = Exception.class)\n");
        bw.write("\tpublic JSONResponse add(JSONRequest jsonRequest) throws BusinessException {\n");
        bw.write("\t\tJSONObject jsonObjectData = jsonRequest.getJsonObjectData();\n");
        bw.write(String.format("\t\t%s %s = %s.to%sInsert(jsonObjectData);\n", clazzBean, bean, assemble, clazzBean));
        bw.write(String.format("\t\t%s.insertSelective(%s);\n", mapperBeanName, bean));
        bw.write("\t\treturn JSONResponse.success(new JSONObject());\n");
        bw.write("\t}\n\n");

        BuildComment.createFieldComment(bw, "页面更新");
        bw.write("\t@Override\n");
        bw.write("\t@Transactional(rollbackFor = Exception.class)\n");
        bw.write("\tpublic JSONResponse update(JSONRequest jsonRequest) throws BusinessException {\n");
        bw.write("\t\tJSONObject jsonObjectData = jsonRequest.getJsonObjectData();\n");
        bw.write(String.format("\t\t%s %s = %s.to%sUpdate(jsonObjectData);\n", clazzBean, bean, assemble, clazzBean));
        bw.write(String.format("\t\t%s.updateByPrimaryKeySelective(%s);\n", mapperBeanName, bean));
        bw.write("\t\treturn JSONResponse.success(new JSONObject());\n");
        bw.write("\t}\n\n");

        BuildComment.createFieldComment(bw, "页面详情");
        bw.write("\t@Override\n");
        bw.write("\tpublic JSONResponse get(JSONRequest jsonRequest) throws BusinessException {\n");
        bw.write("\t\tJSONObject jsonObjectData = jsonRequest.getJsonObjectData();\n");
        bw.write("\t\tString uuid = AppStringUtils.formatEmptyToNull(jsonObjectData.getString(\"uuid\"));\n");
        bw.write(String.format("\t\t%s %s = %s.selectByPrimaryKey(uuid);\n", clazzBean, bean, mapperBeanName));
        bw.write(String.format("\t\treturn JSONResponse.success(%s.toJSONObject(%s));\n", assemble, bean));
        bw.write("\t}\n\n");

        BuildComment.createFieldComment(bw, "页面删除");
        bw.write("\t@Override\n");
        bw.write("\t@Transactional(rollbackFor = Exception.class)\n");
        bw.write("\tpublic JSONResponse delete(JSONRequest jsonRequest) throws BusinessException {\n");
        bw.write("\t\tJSONObject jsonObjectData = jsonRequest.getJsonObjectData();\n");
        bw.write("\t\tString uuid = AppStringUtils.formatEmptyToNull(jsonObjectData.getString(\"uuid\"));\n");
        bw.write(String.format("\t\t%s.deleteByPrimaryKey(uuid);\n", mapperBeanName));
        bw.write("\t\treturn JSONResponse.success(new JSONObject());\n");
        bw.write("\t}\n\n");



        BuildComment.createFieldComment(bw, "新增批量");
        bw.write("\t@Override\n");
        bw.write("\tpublic Integer addBatch(List<" + beanName + "> listBean) {\n");
        bw.write("\t\tif (listBean == null || listBean.isEmpty()) {\n");
        bw.write("\t\t\treturn 0;\n");
        bw.write("\t\t}\n");
        bw.write("\t\treturn this." + mapperBeanName + ".insertBatch(listBean);\n");
        bw.write("\t}\n\n");

        BuildComment.createFieldComment(bw, "新增批量或修改");
        bw.write("\t@Override\n");
        bw.write("\tpublic Integer addOrUpdateBatch(List<" + beanName + "> listBean) {\n");
        bw.write("\t\tif (listBean == null || listBean.isEmpty()) {\n");
        bw.write("\t\t\treturn 0;\n");
        bw.write("\t\t}\n");
        bw.write("\t\treturn this." + mapperBeanName + ".insertOrUpdateBatch(listBean);\n");
        bw.write("\t}\n\n");

        writeFieldDynamic(tableInfo, bw, beanName, mapperBeanName);
    }

    private static void writeFieldDynamic(TableInfo tableInfo, BufferedWriter bw, String beanName,
            String mapperBeanName) throws IOException {
        Map<String, List<FieldInfo>> keyIndexMap = tableInfo.getKeyIndexMap();
        for (Entry<String, List<FieldInfo>> entry : keyIndexMap.entrySet()) {
            List<FieldInfo> fieldInfoList = entry.getValue();

            Integer index = 0;
            StringBuilder methodName = new StringBuilder();
            StringBuilder methodParam = new StringBuilder();
            StringBuilder methodField = new StringBuilder();
            for (FieldInfo fieldInfo : fieldInfoList) {
                index++;
                String propertyName = fieldInfo.getPropertyName();
                methodName.append(StringUtils.upperCaseFirst(propertyName));
                methodParam.append(fieldInfo.getJavaType() + " " + propertyName);
                methodField.append(propertyName);
                if (index < fieldInfoList.size()) {
                    methodName.append("And");
                    methodParam.append(", ");
                    methodField.append(", ");
                }
            }
            BuildComment.createFieldComment(bw, "根据" + methodName + "查询");
            String selectMethodName = "selectBy" + methodName;
            bw.write("\t@Override\n");
            bw.write("\tpublic " + beanName + " " + selectMethodName + "(" + methodParam + ") {\n");
            bw.write("\t\treturn this." + mapperBeanName + "." + selectMethodName + "(" + methodField + ");\n");
            bw.write("\t}\n\n");

            BuildComment.createFieldComment(bw, "根据" + methodName + "更新");
            String updateMethodName = "updateBy" + methodName;
            bw.write("\t@Override\n");
            bw.write("\tpublic Integer " + updateMethodName + "(" + beanName + " bean, " + methodParam + ") {\n");
            bw.write("\t\treturn this." + mapperBeanName + "." + updateMethodName + "(bean, " + methodField + ");\n");
            bw.write("\t}\n\n");

            BuildComment.createFieldComment(bw, "根据" + methodName + "删除");
            String deleteMethodName = "deleteBy" + methodName;
            bw.write("\t@Override\n");
            bw.write("\tpublic Integer " + deleteMethodName + "(" + methodParam + ") {\n");
            bw.write("\t\treturn this." + mapperBeanName + "." + deleteMethodName + "(" + methodField + ");\n");
            bw.write("\t}\n\n");
        }
    }

    private static void writeImport(BufferedWriter bw, String beanName, String beanParamName, String interfaceName,
            String mapperName) throws IOException {
        bw.write("import java.util.List;\n");
        bw.write("import java.util.ArrayList;\n");
        bw.write("import javax.annotation.Resource;\n");
        bw.write("import org.springframework.stereotype.Service;\n");
        bw.write("import org.springframework.transaction.annotation.Transactional;\n");
        bw.write("import com.alibaba.fastjson.JSONObject;\n");
        bw.write("import com.liuhongwei.test.entity.vo.JSONRequest;\n");
        bw.write("import com.liuhongwei.test.entity.vo.JSONResponse;\n");
        bw.write("import com.liuhongwei.test.exception.BusinessException;\n");
        bw.write("import com.liuhongwei.test.entity.query.Page;\n");
        bw.write("import com.liuhongwei.test.utils.AppStringUtils;");
        bw.write("import " + Constants.PACKAGE_PO + "." + beanName + ";\n");
        bw.write("import " + Constants.PACKAGE_QUERY + "." + beanParamName + ";\n");
        bw.write("import " + Constants.PACKAGE_SERVICE + "." + interfaceName + ";\n");
        bw.write("import " + Constants.PACKAGE_MAPPERS + "." + mapperName + ";\n\n");
        bw.write("import " + Constants.PACKAGE_ASSEMBLE + "." + beanName + Constants.SUFFIX_ASSEMBLE + ";\n");
    }


    public static void main(String[] args) {
        List<TableInfo> tableInfoList = BuildTable.getTable();
        for (TableInfo tableInfo : tableInfoList) {
            BuildServiceImpl.execute(tableInfo);
        }
    }

}
